﻿#include "businessuser.h"
#include "businesssql.h"
#include "businessnetwork.h"
#include <protocol/protocolConverter.h>
#include <Debug/DEBUG.hpp>
#include <cstring>

// connect a new user
void BusinessUser::newLoginUser(ID id, const hv::SocketChannelPtr& channel) {
    channelID2userID[channel->id()] = id;
}
// disconnect a user
void BusinessUser::disconnect(const hv::SocketChannelPtr& channel) {
    UserManager& manager = UserManager::getInstance();
    if (!channelID2userID.count(channel->id())) {
        // if login failed , return
        return;
    }
    ID userID = channelID2userID[channel->id()];
    // store user message to sqlite
    auto userMessage = manager.getTargetUser(userID);
    // erase account2Channel
    BusinessNetWork::getInstance().eraseSocketChannel(userID);

    // delete online user message
    manager.deleteTargetUser(userID);

    channelID2userID.erase(channel->id());
}

bool BusinessUser::varifyUser(const std::string &account, const std::string &password)
{
    // query data base
    BusinessSQL& sql = BusinessSQL::getInstance();
    return sql.verifyAUser(account, password);
}

void BusinessUser::recvReplyOfFriendApply(std::shared_ptr<Protocol> protocol, const hv::SocketChannelPtr &channel)
{
    ProtocolConverter converter;
    converter.setProtocolOption(BusinessNetWork::getInstance().getProtocolOption());
    converter.parseData((unsigned char*)protocol->data());

    int subType = std::get<int64_t>(converter.getHeaderField(1));

    uint64_t replyID = std::get<int64_t>(converter.getHeaderField(2));
    uint64_t applyID = std::get<int64_t>(converter.getHeaderField(3));

    BusinessSQL& sql = BusinessSQL::getInstance();

    if (subType == 7) {
        // accept

        sql.updateOrInsertFriendship(applyID, replyID, "accepted");
        sql.updateOrInsertFriendship(replyID, applyID, "accepted");


    } else {
        // reject
        sql.updateOrInsertFriendship(applyID, replyID, "declined");
    }


}

void BusinessUser::recvApplyOfFriend(std::shared_ptr<Protocol> protocol, const hv::SocketChannelPtr &channel)
{
    ProtocolConverter converter;
    converter.setProtocolOption(BusinessNetWork::getInstance().getProtocolOption());
    converter.parseData((unsigned char*)protocol->data());
    // get target account
    std::string targetAccount;
    targetAccount.resize(converter.getParsedDataSize(), '\0');
    converter.copyParsedData((void *)targetAccount.c_str());
    // check target user if exist

    nlohmann::json targetUser = BusinessSQL::getInstance().queryAUser(targetAccount);
    if (targetUser.empty()) {
        // not exist, return to user
        std::string message = "未找到该用户，请检查用户名是否正确！";
        BusinessNetWork::getInstance().sendMessageToClient(channel,
                                                           6, 4, 0, 0, 0,
                                                           (unsigned char *)message.c_str(), message.size());
        return ;
    }
    // exist, check relation

    uint64_t applyID = std::get<int64_t>(converter.getHeaderField(2));
    uint64_t targetID = targetUser["UserID"];

    if (applyID == targetID) {
        std::string message = "无法添加自己为好友！";
        BusinessNetWork::getInstance().sendMessageToClient(channel,
                                                           6, 4, 0, 0, 0,
                                                           (unsigned char *)message.c_str(), message.size());

    }


    std::string relation = BusinessSQL::getInstance().getRelation(applyID, targetID);
    // only relation not exist or be rejected that can be apply again
    if (relation.empty() || relation == "declined") {
        std::string message = "已成功发出申请！";
        BusinessNetWork::getInstance().sendMessageToClient(channel,
                                                           6, 4, 0, 0, 0,
                                                           (unsigned char *)message.c_str(), message.size());

        // update database

        BusinessSQL::getInstance().updateOrInsertFriendship(applyID, targetID, "pending");


    } else {
        std::string message = "当前已发出申请或被拉黑，申请失败！";
        BusinessNetWork::getInstance().sendMessageToClient(channel,
                                                           6, 4, 0, 0, 0,
                                                           (unsigned char *)message.c_str(), message.size());
    }



    // update database
    BusinessSQL::getInstance().updateOrInsertFriendship(applyID, targetID, "pending");

}

void BusinessUser::refreshUserList(std::shared_ptr<Protocol> protocol, const hv::SocketChannelPtr &channel)
{
    ProtocolConverter converter;
    converter.setProtocolOption(BusinessNetWork::getInstance().getProtocolOption());
    converter.parseData((unsigned char*)protocol->data());
    // get account
    std::string account;
    account.resize(converter.getParsedDataSize(), '\0');
    converter.copyParsedData((void *)account.c_str());

    BusinessSQL& sql = BusinessSQL::getInstance();
    nlohmann::json friendMessage = sql.queryAllTheUserOfTargetRelation(account);
    // get all the pending user
    nlohmann::json pendingFriend = sql.queryAllTheUserOfTargetRelation(account, "pending");
    nlohmann::json message;

    message["friendMessage"] = friendMessage;
    message["pendingMessage"] = pendingFriend;

    std::string messageStr = message.dump();

    BusinessNetWork& net = BusinessNetWork::getInstance();

    net.sendMessageToClient(channel,
                            6, 5, 0, 0, 0,
                            (unsigned char*)messageStr.c_str(), messageStr.size());

}

void BusinessUser::ReplyGetTargetUser(std::shared_ptr<Protocol> protocol, const hv::SocketChannelPtr &channel)
{
    ProtocolConverter converter;
    converter.setProtocolOption(BusinessNetWork::getInstance().getProtocolOption());
    converter.parseData((unsigned char*)protocol->data());
    // get account
    if (converter.getParsedDataSize()!= 0) {
        // according to account
        std::string account;
        account.resize(converter.getParsedDataSize(), '\0');
        converter.copyParsedData((void *)account.c_str());

        uint64_t id = std::get<int64_t>(converter.getHeaderField(2));
        User& user = getTargetUser(id);
        std::string applyAccount = user["Account"];
        uint64_t point = std::get<int64_t>(converter.getHeaderField(4));

        nlohmann::json targetUser = BusinessSQL::getInstance().quertAUserToUser(applyAccount, account);
        std::string messageStr = targetUser.dump();
        DEBUG_INFO("remote query user info");
        DEBUG_INFO(messageStr);
        BusinessNetWork::getInstance().sendMessageToClient(channel,
                                                           2, 11, 0, 0, point,
                                                           (unsigned char *)messageStr.c_str(), messageStr.size());

    } else {
        //according to userID
        uint64_t applyID = std::get<int64_t>(converter.getHeaderField(2));
        uint64_t targetID = std::get<int64_t>(converter.getHeaderField(3));

        nlohmann::json targetUser = BusinessSQL::getInstance().queryAUser(targetID);
        std::string status = BusinessSQL::getInstance().getRelation(targetID, applyID);
        targetUser["Status"] = status;
        std::string messageStr = targetUser.dump();
        uint64_t point = std::get<int64_t>(converter.getHeaderField(4));
        BusinessNetWork::getInstance().sendMessageToClient(channel,
                                                           2, 11, 0, 0, point,
                                                           (unsigned char *)messageStr.c_str(), messageStr.size());
    }
}

void BusinessUser::eraseFriend(std::shared_ptr<Protocol> protocol, const hv::SocketChannelPtr &channel)
{
    ProtocolConverter converter;
    converter.setProtocolOption(BusinessNetWork::getInstance().getProtocolOption());
    converter.parseData((unsigned char*)protocol->data());

    uint64_t sourceID = std::get<int64_t>(converter.getHeaderField(2));
    uint64_t targetID = std::get<int64_t>(converter.getHeaderField(3));

    BusinessSQL::getInstance().eraseFriend(sourceID, targetID);

}

void BusinessUser::recvUpdateAvatar(std::shared_ptr<Protocol> protocol, const hv::SocketChannelPtr &channel)
{
    ProtocolConverter converter;
    converter.setProtocolOption(BusinessNetWork::getInstance().getProtocolOption());
    converter.parseData((unsigned char*)protocol->data());

    uint64_t sourceID = std::get<int64_t>(converter.getHeaderField(2));
    int avatar = std::get<int64_t>(converter.getHeaderField(3));

    BusinessSQL::getInstance().updateAvatar(sourceID, avatar);
}

User &BusinessUser::getTargetUser(uint64_t id)
{
    UserManager& userManager = UserManager::getInstance();
    if (!userManager.isExist(id)) {
        User temp = BusinessSQL::getInstance().queryAUser(id);
        User& one = userManager.createNewUser(temp["UserID"], temp["Account"]);
        one["Avatar"] = temp["Avatar"];
    }
    return userManager.getTargetUser(id);
}

User &BusinessUser::getTargetUser(const std::string &account)
{
    UserManager& userManager = UserManager::getInstance();
    if (!userManager.isExist(account)) {
        User temp = BusinessSQL::getInstance().queryAUser(account);
        User& one = userManager.createNewUser(temp["UserID"], temp["Account"]);
        one["Avatar"] = temp["Avatar"];
    }
    return userManager.getTargetUser(account);
}
